package com.kh.rationaldrugreview.service;

import com.kh.rationaldrugreview.dto.PatientContext;
import com.kh.rationaldrugreview.dto.RiskItem;
import com.kh.rationaldrugreview.enums.RiskFactor;
import com.kh.rationaldrugreview.enums.RiskLevel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 风险计算器
 * Risk Calculator Service
 */
@Slf4j
@Service
public class RiskCalculator {
    
    /**
     * 计算综合风险等级
     */
    public RiskLevel calculateOverallRisk(List<RiskItem> riskItems) {
        if (riskItems == null || riskItems.isEmpty()) {
            return RiskLevel.NONE;
        }
        
        // 获取最高单项风险等级
        RiskLevel maxRiskLevel = riskItems.stream()
            .map(RiskItem::getRiskLevel)
            .reduce(RiskLevel.NONE, RiskLevel::max);
        
        // 计算总风险分值
        int totalScore = riskItems.stream()
            .mapToInt(item -> item.getScore() != null ? item.getScore() : 
                item.getRiskFactor() != null ? item.getRiskFactor().getScore() : 0)
            .sum();
        
        // 统计各风险等级数量
        Map<RiskLevel, Long> riskCounts = riskItems.stream()
            .collect(Collectors.groupingBy(
                RiskItem::getRiskLevel,
                Collectors.counting()
            ));
        
        // 应用组合风险升级规则
        RiskLevel adjustedRisk = applyComboRiskRules(maxRiskLevel, riskCounts, totalScore);
        
        log.debug("Risk calculation: maxRisk={}, totalScore={}, adjustedRisk={}", 
            maxRiskLevel, totalScore, adjustedRisk);
        
        return adjustedRisk;
    }
    
    /**
     * 计算患者特征风险系数
     */
    public double calculatePatientRiskFactor(PatientContext patient) {
        double factor = 1.0;
        
        // 年龄因子
        if (patient.getAge() != null) {
            if (patient.getAge() < 1) {        // 新生儿
                factor += 0.8;
            } else if (patient.getAge() < 18) { // 儿童青少年
                factor += 0.4;
            } else if (patient.getAge() >= 75) { // 高龄老人
                factor += 0.6;
            } else if (patient.getAge() >= 65) { // 老年人
                factor += 0.3;
            }
        }
        
        // 妊娠哺乳因子
        if (Boolean.TRUE.equals(patient.getIsPregnant())) {
            factor += 0.7;
            if ("孕早期".equals(patient.getPregnancyStatus())) {
                factor += 0.3; // 孕早期风险更高
            }
        }
        
        if (Boolean.TRUE.equals(patient.getIsLactating())) {
            factor += 0.4;
        }
        
        // 器官功能因子
        if (patient.hasRenalImpairment()) {
            if ("重度不全".equals(patient.getRenalFunction()) || 
                patient.getRenalFunction().contains("透析")) {
                factor += 0.8;
            } else if ("中度不全".equals(patient.getRenalFunction())) {
                factor += 0.5;
            } else {
                factor += 0.2;
            }
        }
        
        if (patient.hasHepaticImpairment()) {
            if ("重度不全".equals(patient.getHepaticFunction())) {
                factor += 0.7;
            } else if ("中度不全".equals(patient.getHepaticFunction())) {
                factor += 0.4;
            } else {
                factor += 0.2;
            }
        }
        
        // 疾病状态因子
        if (Boolean.TRUE.equals(patient.getHasHeartDisease())) {
            factor += 0.3;
        }
        if (Boolean.TRUE.equals(patient.getHasDiabetes())) {
            factor += 0.2;
        }
        if (Boolean.TRUE.equals(patient.getHasHypertension())) {
            factor += 0.1;
        }
        
        // 过敏史因子
        if (patient.getAllergies() != null && !patient.getAllergies().isEmpty()) {
            factor += 0.3;
        }
        
        log.debug("Patient risk factor calculated: {} for patient profile: {}", 
            factor, patient.getRiskProfileSummary());
        
        return Math.min(factor, 3.0); // 限制最大系数为3.0
    }
    
    /**
     * 应用组合风险升级规则
     */
    private RiskLevel applyComboRiskRules(RiskLevel maxRisk, Map<RiskLevel, Long> riskCounts, int totalScore) {
        // 规则1: 如果已经是极高风险，直接返回
        if (maxRisk == RiskLevel.CRITICAL) {
            return RiskLevel.CRITICAL;
        }
        
        // 规则2: 多个高风险项升级为极高风险
        long highRisks = riskCounts.getOrDefault(RiskLevel.HIGH, 0L);
        if (highRisks >= 2) {
            return RiskLevel.CRITICAL;
        }
        
        // 规则3: 高风险+多个中风险升级为极高风险
        long mediumRisks = riskCounts.getOrDefault(RiskLevel.MEDIUM, 0L);
        if (maxRisk == RiskLevel.HIGH && mediumRisks >= 3) {
            return RiskLevel.CRITICAL;
        }
        
        // 规则4: 多个中风险升级为高风险
        if (mediumRisks >= 4) {
            return RiskLevel.HIGH;
        }
        
        // 规则5: 总分值升级规则
        if (totalScore >= 150) {
            return RiskLevel.CRITICAL;
        } else if (totalScore >= 100) {
            return RiskLevel.max(maxRisk, RiskLevel.HIGH);
        } else if (totalScore >= 60) {
            return RiskLevel.max(maxRisk, RiskLevel.MEDIUM);
        }
        
        // 规则6: 大量低风险项升级
        long lowRisks = riskCounts.getOrDefault(RiskLevel.LOW, 0L);
        if (lowRisks >= 8) {
            return RiskLevel.max(maxRisk, RiskLevel.MEDIUM);
        }
        
        return maxRisk;
    }
    
    /**
     * 计算特定药物组合的相互作用风险
     */
    public RiskLevel calculateInteractionRisk(List<String> drugs, Map<String, Object> interactionData) {
        if (drugs == null || drugs.size() < 2 || interactionData == null) {
            return RiskLevel.NONE;
        }
        
        // 基于相互作用数据计算风险
        String severity = (String) interactionData.getOrDefault("severity", "mild");
        String mechanism = (String) interactionData.getOrDefault("mechanism", "");
        
        return switch (severity.toLowerCase()) {
            case "severe", "major" -> RiskLevel.HIGH;
            case "moderate" -> RiskLevel.MEDIUM;
            case "mild", "minor" -> RiskLevel.LOW;
            default -> RiskLevel.NONE;
        };
    }
    
    /**
     * 计算妊娠风险等级
     */
    public RiskLevel calculatePregnancyRisk(String pregnancyCategory, String trimester) {
        if (pregnancyCategory == null) {
            return RiskLevel.NONE;
        }
        
        RiskLevel baseRisk = switch (pregnancyCategory.toUpperCase()) {
            case "X" -> RiskLevel.CRITICAL;
            case "D" -> RiskLevel.HIGH;
            case "C" -> RiskLevel.MEDIUM;
            case "B" -> RiskLevel.LOW;
            case "A" -> RiskLevel.NONE;
            default -> RiskLevel.NONE;
        };
        
        // 孕早期风险更高
        if ("孕早期".equals(trimester) && baseRisk.getLevel() > RiskLevel.NONE.getLevel()) {
            // 升级一个等级（但不超过CRITICAL）
            int upgradedLevel = Math.min(baseRisk.getLevel() + 1, RiskLevel.CRITICAL.getLevel());
            return RiskLevel.values()[upgradedLevel];
        }
        
        return baseRisk;
    }
    
    /**
     * 计算年龄适用性风险
     */
    public RiskLevel calculateAgeRisk(Integer patientAge, Integer minAge, Integer maxAge) {
        if (patientAge == null) {
            return RiskLevel.NONE;
        }
        
        boolean outsideRange = false;
        int deviation = 0;
        
        if (minAge != null && patientAge < minAge) {
            outsideRange = true;
            deviation = minAge - patientAge;
        } else if (maxAge != null && patientAge > maxAge) {
            outsideRange = true;
            deviation = patientAge - maxAge;
        }
        
        if (!outsideRange) {
            return RiskLevel.NONE;
        }
        
        // 根据偏离程度确定风险等级
        if (deviation >= 10) {
            return RiskLevel.HIGH;
        } else if (deviation >= 5) {
            return RiskLevel.MEDIUM;
        } else {
            return RiskLevel.LOW;
        }
    }
    
    /**
     * 计算器官功能风险
     */
    public RiskLevel calculateOrganFunctionRisk(String patientFunction, String requiredFunction) {
        if (patientFunction == null || requiredFunction == null) {
            return RiskLevel.NONE;
        }
        
        // 功能等级映射
        Map<String, Integer> functionLevels = Map.of(
            "正常", 4,
            "轻度不全", 3,
            "中度不全", 2,
            "重度不全", 1,
            "衰竭", 0,
            "透析", 0
        );
        
        int patientLevel = functionLevels.getOrDefault(patientFunction, 4);
        int requiredLevel = functionLevels.getOrDefault(requiredFunction, 4);
        
        if (patientLevel >= requiredLevel) {
            return RiskLevel.NONE;
        }
        
        int deficit = requiredLevel - patientLevel;
        return switch (deficit) {
            case 1 -> RiskLevel.LOW;
            case 2 -> RiskLevel.MEDIUM;
            case 3 -> RiskLevel.HIGH;
            default -> RiskLevel.CRITICAL;
        };
    }
    
    /**
     * 根据多个风险因子计算综合分值
     */
    public int calculateCompositeScore(List<RiskFactor> factors, PatientContext patient) {
        if (factors == null || factors.isEmpty()) {
            return 0;
        }
        
        // 基础分值
        int baseScore = factors.stream()
            .mapToInt(RiskFactor::getScore)
            .sum();
        
        // 应用患者风险系数
        double patientFactor = calculatePatientRiskFactor(patient);
        
        // 应用协同效应
        double synergyFactor = calculateSynergyFactor(factors);
        
        return (int) Math.round(baseScore * patientFactor * synergyFactor);
    }
    
    /**
     * 计算风险因子间的协同效应
     */
    private double calculateSynergyFactor(List<RiskFactor> factors) {
        double factor = 1.0;
        
        // 妊娠相关因子的协同效应
        long pregnancyFactors = factors.stream()
            .filter(RiskFactor::isPregnancyRelated)
            .count();
        if (pregnancyFactors > 1) {
            factor += 0.2 * (pregnancyFactors - 1);
        }
        
        // 器官功能相关因子的协同效应
        long organFactors = factors.stream()
            .filter(RiskFactor::isOrganFunctionRelated)
            .count();
        if (organFactors > 1) {
            factor += 0.15 * (organFactors - 1);
        }
        
        // 高严重性因子的协同效应
        long highSeverityFactors = factors.stream()
            .filter(RiskFactor::isHighSeverity)
            .count();
        if (highSeverityFactors > 1) {
            factor += 0.3 * (highSeverityFactors - 1);
        }
        
        return Math.min(factor, 2.0); // 限制最大协同系数
    }
}